﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;
using Microsoft.Surface.Presentation.Input;
using ScrumTable.BL.DM.DataManagement;
using ScrumTable.Common;
using ScrumTable.Common.Collections;
using ScrumTable.Common.Data;
using ScrumTable.Config.ElementManagement;
using ScrumTable.UI.View.Converter;
using ScrumTable.UI.View.CustomControl;
using ScrumTable.UI.View.Rule;
using ScrumTable.UI.View.Util;
using ScrumTable.UI.View.WinTouch.CustomControl;
using ScrumTable.UI.View.WinTouch.UserControls;
using ScrumTable.UI.View.WinTouch.UserControls.HtmlRichText.Controls;
using ScrumTable.UI.ViewModel;

#endregion

namespace ScrumTable.UI.View.WinTouch.Util
{

    /// <summary>
    /// CreateDynamicUiFactory create the dynamic gui from the viewmodel meta
    /// </summary>
    public class CreateDynamicUiFactory
    {

        #region Decleration
        //--------------------------------------------------------------------
        // Decleration
        //--------------------------------------------------------------------
        private bool _showGroupStyle = true;
        #endregion


        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------
        public FrameworkElement GetStackedControl(IScrumItemViewModel<ScrumItemBase> model, string fieldName)
        {
            DomainMeta field = GetMetaField(model, fieldName);
            if (field == null)
            {
                return null;
            }
            Control control = GetControl(model, field);
            Panel panel;
            if (_showGroupStyle)
            {
                control.MaxWidth = control.MinWidth = control.Width = 80;
                panel = new StackPanel() {Orientation = Orientation.Horizontal, MaxHeight = 40, Margin = new Thickness(0, 1, 0, 1)};
                panel.Children.Add(new Label() { Content = field.DisplayName, Width = 70, MaxHeight = 40 });
                panel.Children.Add(control);
            }
            else
            {
                panel = new DockPanel() { LastChildFill = true, Margin = new Thickness(0,5,0,0)};
                var label = new Label() { Content = field.DisplayName, Width = 90, MaxHeight = 40, Padding = new Thickness(0,5,5,5)};
                DockPanel.SetDock(label, Dock.Left);
                panel.Children.Add(label);
                DockPanel.SetDock(control, Dock.Right);
                panel.Children.Add(control);
                
            }
            
            return new DynamicErrorControl(panel, model, field.Name) {Name = field.Name};
        }

        private static DomainMeta GetMetaField(IScrumItemViewModel<ScrumItemBase> model, string fieldName)
        {
            return model.Original.ItemType.FieldMeta.TryGetByName(fieldName);
        }

        private static Control GetControl(IScrumItemViewModel<ScrumItemBase> model, DomainMeta field)
        {
            Control control;
            if (!field.SuggestedValues.IsEmpty())
            {
                control = new ValueSelector {SelectedItem = model, DomainMeta = field}; //, MaxHeight = 40, MaxWidth = 70
            }
            else
            {

                ChangeConvertTypeRule rule = new ChangeConvertTypeRule() {Type = field.FieldType};
                IValueConverter converter = new ConverterGenerics() {TargetType = typeof (object), SourceType = field.FieldType};

                switch (field.FieldTypeFormat)
                {
                    case DataType.Integer:
                        control = new DigitBox();
                        converter = new ConverterUpdatePreventerFocusedElement(control, converter);
                        BindingUtil.BindSourcePath(control, TextBox.TextProperty, "[" + field.Name + "]", model, converter, rule);
                        control.Padding = new Thickness(5, 5, 5, 5);
                        control.VerticalContentAlignment = VerticalAlignment.Center;              
                        break;
                    case DataType.Html:
                        control = new RichTextEditor();
                        converter = new ConverterUpdatePreventerFocusedElement(control, converter);
                        BindingUtil.BindSourcePath(control, RichTextEditor.TextProperty, "[" + field.Name + "]", model, converter, rule);
                        break;
                    case DataType.String:
                    case DataType.PlainText:
                        control = new SurfaceTextBox();
                        converter = new ConverterUpdatePreventerFocusedElement(control, converter);
                        BindingUtil.BindSourcePath(control, TextBox.TextProperty, "[" + field.Name + "]", model, converter, rule);
                        break;
                    case DataType.Boolean:
                        /*TODO Try it, if it works*/
                        control = new SurfaceCheckBox();
                        converter = new ConverterUpdatePreventerFocusedElement(control, converter);
                        BindingUtil.BindSourcePath(control, ToggleButton.IsCheckedProperty, "[" + field.Name + "]", model, converter, rule);
                        break;
                    case DataType.Double:
                        control = new DigitBox();
                        converter = new ConverterUpdatePreventerFocusedElement(control, converter);
                        BindingUtil.BindSourcePath(control, TextBox.TextProperty, "[" + field.Name + "]", model, converter, rule);
                        control.Padding = new Thickness(5, 5, 5, 5);
                        break;
                        //case DataType.DateTime:
                        //    throw new ArgumentException(field.FieldTypeFormat.ToString());
                        //    break;
                    default:
                        throw new ArgumentException(field.FieldTypeFormat.ToString());
                }
                
            }
            control.Margin = new Thickness(3,0,3,0);
            return control;
        }


        /// <summary>
        /// Create a GUI based on a model and the settings
        /// </summary>
        /// <param name="model"></param>
        /// <param name="uiSetting"></param>
        /// <param name="showGroupStyle">creates groupboxes around each group</param>
        /// <returns></returns>
        public static UIElement CreateDynamicPart(IScrumItemViewModel<ScrumItemBase> model, UiElementConfig uiSetting, bool showGroupStyle=true)
        {
            if( model == null||model.Original == null)
            {
                return null;
            }
            var factory = new CreateDynamicUiFactory(){_showGroupStyle = showGroupStyle};
            var uiElement = factory.CreateFirstGroup(model, uiSetting);
            return uiElement;
        }


        /// <summary>
        /// Create a GUI based on a model and the settings
        /// </summary>
        /// <param name="model"></param>
        /// <param name="uiSetting"></param>
        /// <returns></returns>
        public static UIElement CreateMemoParts(IScrumItemViewModel<ScrumItemBase> model, UiElementConfig uiSetting)
        {
            if(model == null || model.Original == null) { return null; }
            if (uiSetting.MemoFields != null && uiSetting.MemoFields.Count > 0)
            {
                var tabControl = new TabControl();
                tabControl.IsTabStop = false;
                tabControl.Padding = new Thickness();
                foreach(var memo in uiSetting.MemoFields)
                {
                    var tabItem = new TabItem {IsTabStop = false, Padding = new Thickness(0)};

                    DomainMeta field = GetMetaField(model, memo);
                    if (field == null)
                    {
                        return null;
                    }
                    tabItem.Header = field.DisplayName;
                    var control = GetControl(model, field);
                    if (control is SurfaceTextBox)
                    {
                        ((SurfaceTextBox) control).AcceptsReturn = true;
                        ((SurfaceTextBox) control).TextWrapping = TextWrapping.Wrap;
                    }
                   
                    ScrollViewer.SetVerticalScrollBarVisibility(control, ScrollBarVisibility.Auto);
                    tabItem.Content = control;
                    tabControl.Items.Add(tabItem);
                }
                return tabControl;
            }
            return null;
        }

        private FrameworkElement CreateFirstGroup(IScrumItemViewModel<ScrumItemBase> model, UiElementConfig uiSetting)
        {
            Panel wrapPanel = _showGroupStyle ? (Panel)new WrapPanel() { Orientation = Orientation.Vertical } : new StackPanel() { Orientation = Orientation.Vertical };
            UIElement panel = CreatePanelContainer("Values", wrapPanel);
            Panel stackPanel = _showGroupStyle ? (Panel)new WrapPanelAlignAnimated() { Orientation = Orientation.Vertical } : new StackPanel() { Orientation = Orientation.Vertical };

            foreach (var field in uiSetting.Children)
            {
                FrameworkElement element = CreateTreeGroup(model, field);
                if ((element != null) && !(_showGroupStyle ? element is GroupBox : element is StackPanel))
                {
                    wrapPanel.Children.Add(element);
                }
                else if (element != null)
                {
                    stackPanel.Children.Add(element);
                }
            }

            if (wrapPanel.Children.Count > 0)
            {
                stackPanel.Children.Add(panel);
            }
            return stackPanel;
        }

        private FrameworkElement CreatePanelContainer(string header, FrameworkElement subContainer)
        {
            
            if(_showGroupStyle)
            {
                return new GroupBox() { Header = header, Content = subContainer, Foreground = Brushes.Black };
            }
            else
            {
                var panel = new StackPanel() {Margin = new Thickness(0, 20, 0, 0)};
                panel.Children.Add(new Label() { Content = header, FontWeight = FontWeights.Bold, Style = Application.Current.FindResource("ContentTitleLabel") as Style });
                panel.Children.Add(subContainer);
                return panel;
            }
        }
        private FrameworkElement CreateTreeGroup(IScrumItemViewModel<ScrumItemBase> model, UiElementBase uiSetting)
        {
            if(uiSetting.Children == null || uiSetting.Children.Count==0)
            {
                //break condition 
                return GetStackedControl(model, uiSetting.Name);
            }
            Panel stackPanel = _showGroupStyle ? (Panel)new WrapPanel() { Orientation = Orientation.Vertical } : new StackPanel() { Orientation = Orientation.Vertical }; 
            
            foreach( var field in uiSetting.Children)
            {
                FrameworkElement element = CreateTreeGroup(model, field);
                if (element != null)
                {
                    stackPanel.Children.Add(element);
                }
            }
            
            var panel = CreatePanelContainer(uiSetting.Name, stackPanel); 
            return panel;
        }
       
        #endregion

       
    }

  
}
